package com.verlet.springbootdemo.aop;

import com.verlet.springbootdemo.annotation.Resubmit;
import com.verlet.springbootdemo.common.ServerResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * 重复提交检验
 *
 * @author verlet
 * @date 2021-07-21 00:37
 */
@Slf4j
@Order(2)
@Aspect
@Component
public class ResubmitAspect {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Pointcut(value = "@annotation(resubmit)")
    public void pointcut(Resubmit resubmit) {
    }

    /**
     * 环绕通知：可实现任意通知，可调用 proceedingJoinPoint.proceed() 方法使目标方法继续执行
     *
     * @param proceedingJoinPoint
     * @param resubmit
     * @return
     * @throws Throwable
     */
    @Around(value = "pointcut(resubmit)", argNames = "proceedingJoinPoint,resubmit")
    public Object around(ProceedingJoinPoint proceedingJoinPoint, Resubmit resubmit) throws Throwable {
        StringBuilder cache = new StringBuilder();
        String cacheKey = resubmit.cacheKey();
        MethodSignature methodSignature = ((MethodSignature) proceedingJoinPoint.getSignature());
        String[] names = methodSignature.getParameterNames();
        Object[] args = proceedingJoinPoint.getArgs();
        if (StringUtils.isNotBlank(cacheKey)) {
            for (int i = 0; i < names.length; i++) {
                if (names[i].equals(resubmit.cacheKey())) {
                    cache.append(args[i]);
                    break;
                }
            }
        }
        if (StringUtils.isBlank(cache.toString()) && args.length > 1) {
            cache.append(args[0] == null ? "" : args[0]);
        }
        cache.insert(0, methodSignature.getName() + ":").insert(0, resubmit.cachePrefix());
        if (StringUtils.isNotBlank(stringRedisTemplate.opsForValue().get(cache.toString()))) {
            return ServerResponse.createByErrorMessage("当前资源处理中，请稍后再试！");
        }

        stringRedisTemplate.opsForValue().set(cache.toString(), String.valueOf(System.currentTimeMillis()), resubmit.delaySeconds(), TimeUnit.SECONDS);
        return proceedingJoinPoint.proceed();
    }

}
